#include "los_typedef.h"
#include "los_hwi.h"
#include "crc.h"
#include "pcrambox.h"
#include "los_task.h"
#include "string.h"

/**
 * TLSF include
 */
#include "los_compiler.h"
#include "los_hwi.h"
#include "los_task.ph"
#include "los_printf.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */ 

/**
 * The address of the static memory pool must be aligned to the boundary of 4.
 */
#define OS_BOXMEM_BASE_ALIGN  4
#define BOXMEM_ALIGN(value, alignSize)  ((UINT32)(value) | ((UINT32)(alignSize - 1))) + 1

/**
 * Get the address of the next memory node in the static memory pool.
 */
#define OS_pcrambox_NODE_NEXT(addr, uwBlkSize)  (VOID *)((UINT32)(addr) + (uwBlkSize))

/**
 * The magic word of the memory box.
 */
#define pcrambox_magicsize              2
#ifdef LOS_pcrambox_MAGIC_CHECK
#define OS_pcrambox_MAGIC              0xFFAA
#define OS_pcrambox_SET_MAGIC(addr)    *((UINT16 *)(addr)) = OS_pcrambox_MAGIC
#define OS_pcrambox_CHECK_MAGIC(addr)  ((*((UINT16 *)(addr)) == OS_pcrambox_MAGIC) ? LOS_OK: LOS_NOK)
#else
#define OS_pcrambox_SET_MAGIC(addr)
#define OS_pcrambox_CHECK_MAGIC(addr)  LOS_OK
#endif

/**
 * Get the address of memory block according to the magic word information.
 */
#define pcram_alloc_mempool_addr(addr)        (VOID *)((UINT32)addr + (UINT32)(2 * g_TVCBSize * g_TVCBNum) + pcrambox_magicsize + sizeof(LOS_MEM_POOL_INFO))
#define pcram_mempool_addr(addr)              (VOID *)((UINT32)addr + (UINT32)(2 * g_TVCBNum * g_TVCBSize) + pcrambox_magicsize)
#define OS_SCLIST_VIB_ADDR(addr)     ((VIB *)((UINT32)addr + SCLIST_TVCB_STRUCT_SIZE))
#define OS_pcrambox_USER_ADDR(addr)  ((VOID *)((UINT32 *)(addr) + LOS_pcrambox_MAGIC_SIZE))
#define OS_pcrambox_NODE_ADDR(addr)  (VOID *)(((UINT32 *)(addr) - LOS_pcrambox_MAGIC_SIZE))
#define OS_ADDR16to32(addr)          ((UINT32)((addr.HI16) << 16) | (UINT32)(addr.LO16))
//#define TIDEqual(TI1, TI2)            (((TI1.TID != TI2.TID)||(TI1.Identifier != TI2.Identifier)) ? LOS_NOK : LOS_OK)
#define TVCBOverflow(addr)           (((UINT32)g_TVBHead + g_TVCBSize * g_TVCBNum) < (UINT32)addr ? LOS_NOK : LOS_OK)
#define isnotEmpty(addr)            (addr.HI16 != 0 && addr.LO16 != 0)
VOID *g_TVBHead = NULL;
UINT16 g_TVCBSize;                       //鍒濆鍖栭噷杩涜璧嬪�兼搷浣�
UINT16 g_VIBSize;                       //璇诲啓鐨勬椂鍊欒浆鎴�8浣嶆嫾璧锋潵
UINT16 g_TVCBNum;

/**
 * TLSF define
 */
extern ST_LOS_TASK g_stLosTask;

#define AARCHPTR UINT32

LITE_OS_SEC_ALW_INLINE static inline INT32 __log2(UINT32 uwWord)
{
    return uwWord ? (sizeof(uwWord) * 8 - CLZ(uwWord) - 1) : 0;
}

LITE_OS_SEC_TEXT static inline INT32 tlsf_ffs(UINT32 uwWord)
{
    return __log2(uwWord & (UINT32)(-(UINT32)uwWord)); /*lint !e501*/
}

LITE_OS_SEC_TEXT static inline INT32 tlsf_fls(UINT32 uwWord)
{
    const INT32 swBit = uwWord ? 32 - CLZ(uwWord) : 0;
    return swBit - 1;
}

#define tlsf_fls_sizet tlsf_fls

/*
 * Block header structure.
 *
 * There are several implementation subtleties involved:
 * - The prev_phys_block field is only valid if the previous pNode is free.
 * - The prev_phys_block field is actually stored at the end of the
 *   previous pNode. It appears at the beginning of this structure only to
 *   simplify the implementation.
 * - The pNext_free / pPrev_free fields are only valid if the pNode is free.
 */
typedef struct LOS_MEM_DYN_NODE {
    /* Points to the previous physical pNode. */
    struct LOS_MEM_DYN_NODE *pstPreNode;
    /* The size of this pNode, excluding the pNode header. */
    UINT32 uwSize;
    /* Next and previous free blocks. */
    struct LOS_MEM_DYN_NODE *pNext_free;
    struct LOS_MEM_DYN_NODE *pPrev_free;
} LOS_MEM_DYN_NODE;

enum tlsf_public {
    SL_INDEX_COUNT_LOG2 = 2,
};

enum tlsf_private {
    /* All allocation sizes and addresses are aligned to 4 bytes. */
    ALIGN_SIZE_LOG2 = 2,
    ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2),
    FL_INDEX_MAX = 30,
    SL_INDEX_COUNT = (1 << SL_INDEX_COUNT_LOG2),
    FL_INDEX_SHIFT = (SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2),
    FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1),
    SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT),
};

typedef struct LOS_MEM_POOL_INFO {
    LOS_MEM_DYN_NODE stBlock_null;
    UINT32 uwPoolSize;
    UINT32 fl_bitmap;
    UINT32 sl_bitmap[FL_INDEX_COUNT];
    LOS_MEM_DYN_NODE *pstBlocks[FL_INDEX_COUNT][SL_INDEX_COUNT];


    UINT32 uwTlsf_AllocCount;
    UINT32 uwTlsf_FreeCount;
} LOS_MEM_POOL_INFO;

/* pool_t: a pNode of memory that TLSF can manage. */
typedef VOID *pool_t;

/* Add/remove memory pools. */
pool_t osMemPoolAdd(VOID *tlsf, VOID *pPool, UINT32 uwBytes);

/* Overheads/limits of internal structures. */
UINT32 osMemHeadSize(VOID);

/* Debugging. */
#define TSLF_CONFIG_DEBUG

#ifdef TLSF_CONFIG_ASSERT
#include <assert.h>
#define tlsf_assert(expr) assert(expr)
#define   alignCheck(align)  tlsf_assert(0 == ((align) & ((align) - 1)) && "must align to a power of two");
#else
#define tlsf_assert(expr) (VOID)(0)
#define   alignCheck(align)
#endif

/*
 * Cast and min/max macros.
 */
#define tlsf_cast(t, exp) ((t)(exp))
#define tlsf_min(a, b) ((a) < (b) ? (a) : (b))
#define tlsf_max(a, b) ((a) > (b) ? (a) : (b))

#define tlsf_offset(a,b) LOS_OFF_SET_OF(a, b)



/*
 * Since pNode sizes are always at least a multiple of 4, the two least
 * significant bits of the size field are used to store the pNode status:
 * - bit 0: whether pNode is busy or free
 * - bit 1: whether previous pNode is busy or free
 */
static const UINT32 block_header_free_bit = 1 << 0;
static const UINT32 block_header_prev_free_bit = 1 << 1;

#define DEBUG_SPACE   4

/*
 * The size of the pNode header exposed to used blocks is the size field.
 * The pstPreNode field is stored *inside* the previous free pNode.
 */
static const UINT32 block_header_overhead = tlsf_offset(LOS_MEM_DYN_NODE, uwSize);

/* User data starts directly after the size field in a used pNode. */
static const UINT32 block_start_offset =
    tlsf_offset(LOS_MEM_DYN_NODE, uwSize) + sizeof(UINT32) + DEBUG_SPACE; /*lint !e413*/

/*
 * A free pNode must be large enough to store its header minus the size of
 * the pstPreNode field, and no larger than the number of addressable
 * bits for FL_INDEX.
 */
static const UINT32 block_size_min =
    sizeof(LOS_MEM_DYN_NODE) - sizeof(LOS_MEM_DYN_NODE *);
static const UINT32 block_size_max = tlsf_cast(UINT32, 1) << FL_INDEX_MAX;

#define control_t LOS_MEM_POOL_INFO

#define OS_MEM_TASKID_SET(node, ID)  \
            do \
            { \
                AARCHPTR uwTmp = (AARCHPTR)(((LOS_MEM_DYN_NODE *)node)->pNext_free); \
                uwTmp &= 0xffff0000; \
                uwTmp |= ID; \
                ((LOS_MEM_DYN_NODE *)node)->pNext_free = (LOS_MEM_DYN_NODE *)uwTmp; \
            }while(0)

#define OS_MEM_TASKID_GET(node)  ((AARCHPTR)(((LOS_MEM_DYN_NODE *)node)->pNext_free) & 0xffff)

VOID osMemInfoPrint(pool_t pPool);
#define IS_ALIGNED(value, alignSize)  (0 == (((AARCHPTR)(value)) & ((AARCHPTR)(alignSize - 1))))
/*
 * LOS_MEM_DYN_NODE member functions.
 */
LITE_OS_SEC_TEXT static VOID osMemNodeSizeSet(LOS_MEM_DYN_NODE *pNode, UINT32 uwSize)
{
    pNode->uwSize = uwSize | (pNode->uwSize & (block_header_free_bit | block_header_prev_free_bit));
}

LITE_OS_SEC_TEXT static UINT32 osMemNodeSizeGet(const LOS_MEM_DYN_NODE *pNode)
{
    return pNode->uwSize & ~(block_header_free_bit | block_header_prev_free_bit);
}

LITE_OS_SEC_TEXT static INT32 osMemEndCheck(const LOS_MEM_DYN_NODE *pNode)
{
    return osMemNodeSizeGet(pNode) == 0;
}

LITE_OS_SEC_TEXT static INT32 os_MemFreeCheck(const LOS_MEM_DYN_NODE *pNode)
{
    return tlsf_cast(INT32, pNode->uwSize & block_header_free_bit);
}

LITE_OS_SEC_TEXT static VOID osMemFreeMark(LOS_MEM_DYN_NODE *pNode)
{
    pNode->uwSize |= block_header_free_bit;
}

LITE_OS_SEC_TEXT static VOID osMemUsedMark(LOS_MEM_DYN_NODE *pNode)
{
    pNode->uwSize &= ~block_header_free_bit;
}

LITE_OS_SEC_TEXT static INT32 osMemPreFreeCheck(const LOS_MEM_DYN_NODE *pNode)
{
    return tlsf_cast(INT32, pNode->uwSize & block_header_prev_free_bit);
}

LITE_OS_SEC_TEXT static VOID osMemPreFreeMark(LOS_MEM_DYN_NODE *pNode)
{
    pNode->uwSize |= block_header_prev_free_bit;
}

LITE_OS_SEC_TEXT static VOID osMemPreUsedMark(LOS_MEM_DYN_NODE *pNode)
{
    pNode->uwSize &= ~block_header_prev_free_bit;
}

LITE_OS_SEC_TEXT LOS_MEM_DYN_NODE *osMemPtrToNode(const VOID *pPtr)
{
    return tlsf_cast(LOS_MEM_DYN_NODE *,
                     tlsf_cast(UINT8*, pPtr) - block_start_offset);
}

LITE_OS_SEC_TEXT static VOID *osMemNodeToPtr(const LOS_MEM_DYN_NODE *pNode)
{
    return tlsf_cast(VOID *,
                     tlsf_cast(UINT8 *, pNode) + block_start_offset);
}

/* Return location of next pNode after pNode of given size. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemPtrOffset(const VOID *pPtr, INT32 swSize)
{
    return tlsf_cast(LOS_MEM_DYN_NODE *, tlsf_cast(AARCHPTR, pPtr) + swSize);
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE * osMemFirstNode(VOID *pPool)
{
    return osMemPtrOffset((const VOID *)((AARCHPTR)pPool + osMemHeadSize()), -(INT32)block_header_overhead); /*lint !e570*/
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemEndNode(pool_t pPool)
{
    return (LOS_MEM_DYN_NODE *)((AARCHPTR)pPool + ((control_t *)pPool)->uwPoolSize - block_start_offset);
}

LITE_OS_SEC_TEXT static AARCHPTR osMemEndPtr(pool_t pPool)
{
    return (AARCHPTR)pPool + ((control_t *)pPool)->uwPoolSize;
}

/* Return location of previous pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNodePre(const LOS_MEM_DYN_NODE *pNode)
{
    tlsf_assert(osMemPreFreeCheck(pNode) && "previous pNode must be free");
    return pNode->pstPreNode;
}

/* Return location of next existing pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNodeNext(const LOS_MEM_DYN_NODE *pNode)
{
    LOS_MEM_DYN_NODE *pNext = osMemPtrOffset(
        tlsf_cast(VOID *, pNode), (INT32)osMemNodeSizeGet(pNode));
    tlsf_assert(!osMemEndCheck(pNode));
    return pNext;
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNextLink(LOS_MEM_DYN_NODE *pNode)
{
    LOS_MEM_DYN_NODE *pNext = osMemNodeNext(pNode);
    pNext->pstPreNode = pNode;
    return pNext;
}

LITE_OS_SEC_TEXT static VOID osMemFreeSet(LOS_MEM_DYN_NODE *pNode)
{
    /* Link the pNode to the next pNode, first. */
    LOS_MEM_DYN_NODE *pNext = osMemNextLink(pNode);
    osMemPreFreeMark(pNext);
    osMemFreeMark(pNode);
}

LITE_OS_SEC_TEXT static VOID osMemUsedSet(LOS_MEM_DYN_NODE *pNode)
{
    LOS_MEM_DYN_NODE *pNext = osMemNodeNext(pNode);
    osMemPreUsedMark(pNext);
    osMemUsedMark(pNode);
}

LITE_OS_SEC_TEXT static AARCHPTR osMemAlignDown(AARCHPTR uwData, UINT32 uwAlign)
{
    alignCheck(uwAlign);
    return uwData - (uwData & (uwAlign - 1));
}

LITE_OS_SEC_TEXT static AARCHPTR osMemAlignUp(AARCHPTR uwData, UINT32 uwAlign)
{
    alignCheck(uwAlign);
    return (uwData + (AARCHPTR)(uwAlign - 1)) & ~((AARCHPTR)(uwAlign - 1));
}

LITE_OS_SEC_TEXT static VOID *osMemAlignPtr(const VOID *pPtr, UINT32 uwAlign)
{
    const AARCHPTR uwAligned = (tlsf_cast(AARCHPTR, pPtr) + (AARCHPTR)(uwAlign - 1)) & ~((AARCHPTR)(uwAlign - 1));
    alignCheck(uwAlign);
    return tlsf_cast(VOID *, uwAligned);
}

LITE_OS_SEC_TEXT static UINT32 osMemReqSizeAdjust(UINT32 uwSize, UINT32 uwAlign)
{
    UINT32 uwAdjust = 0;
    if (uwSize && uwSize < block_size_max)
    {
        const UINT32 uwAligned = osMemAlignUp(uwSize, uwAlign) + block_start_offset;
        uwAdjust = tlsf_max(uwAligned, block_size_min);
    }
    return uwAdjust;
}

LITE_OS_SEC_TEXT static VOID osMemMapInsert(UINT32 uwSize, INT32 *pFli, INT32 *pSli)
{
    INT32 swFl, swSl;
    if (uwSize < SMALL_BLOCK_SIZE)
    {
        /* Store small blocks in first list. */
        swFl = 0;
        swSl = tlsf_cast(INT32, uwSize) / (SMALL_BLOCK_SIZE / SL_INDEX_COUNT);
    }
    else
    {
        swFl = tlsf_fls_sizet(uwSize);
        swSl = tlsf_cast(INT32, uwSize >> (swFl - SL_INDEX_COUNT_LOG2)) ^
             (1 << SL_INDEX_COUNT_LOG2);
        swFl -= (FL_INDEX_SHIFT - 1);
    }

    *pFli = swFl;
    *pSli = swSl;
    //PRINT_ERR("FL = %d, SL = %d\n", swFl,swSl);
}

LITE_OS_SEC_TEXT static VOID osMemMapSearch(UINT32 uwSize, INT32 *pFli, INT32 *pSli)
{
    if (uwSize >= SMALL_BLOCK_SIZE) {
        const UINT32 uwRound = (1 << (tlsf_fls_sizet(uwSize) - SL_INDEX_COUNT_LOG2)) - 1;
        uwSize += uwRound;
    }
    osMemMapInsert(uwSize, pFli, pSli);
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemSuitableNodeSearch(control_t *control,
                                             INT32 *pFli, INT32 *pSli)
{
    INT32 swFl = *pFli;
    INT32 swSl = *pSli;
    UINT32 swSl_map = control->sl_bitmap[swFl] & (((UINT32)~0) << swSl);
    if (!swSl_map) {
        
        /* No pNode exists. Search in the next largest first-level list. */
        const UINT32 swFl_map = control->fl_bitmap & (((UINT32)~0) << (swFl + 1));
        if (!swFl_map) {
            /* No free blocks available, memory has been exhausted. */
        	printf("No free blocks available, memory has been exhausted. \r\n");
            return NULL;
        }

        swFl = tlsf_ffs(swFl_map);
        *pFli = swFl;
        swSl_map = control->sl_bitmap[swFl];
    }
    tlsf_assert(swSl_map && "internal error - second level bitmap is null");
    swSl = tlsf_ffs(swSl_map);
    *pSli = swSl;

    /* Return the first pNode in the free list. */
    return control->pstBlocks[swFl][swSl];
}

LITE_OS_SEC_TEXT static VOID osMemFreeNodeRemove(control_t *control,
                              LOS_MEM_DYN_NODE *pNode,
                              INT32 swFl, INT32 swSl)
{
    LOS_MEM_DYN_NODE *pPrev = pNode->pPrev_free;
    LOS_MEM_DYN_NODE *pNext = pNode->pNext_free;
    tlsf_assert(pPrev && "pPrev_free field can not be null");
    tlsf_assert(pNext && "pNext_free field can not be null");
    pNext->pPrev_free = pPrev;
    pPrev->pNext_free = pNext;
    /* If this pNode is the head of the free list, set new head. */
    if (control->pstBlocks[swFl][swSl] == pNode) {
        control->pstBlocks[swFl][swSl] = pNext;
        /* If the new head is null, clear the bitmap. */
        if (pNext == &control->stBlock_null) {
            control->sl_bitmap[swFl] &= ~(1 << swSl); /*lint !e502*/

            /* If the second bitmap is now empty, clear the fl bitmap. */
            if (!control->sl_bitmap[swFl]) {
                control->fl_bitmap &= ~(1 << swFl); /*lint !e502*/
            }
        }
    }
}

/* Insert a free pNode into the free pNode list. */
LITE_OS_SEC_TEXT static VOID osMemFreeNodeInsert(control_t *control,
                              LOS_MEM_DYN_NODE *pNode,
                              INT32 swFl, INT32 swSl)
{
    LOS_MEM_DYN_NODE *pstCurrent = control->pstBlocks[swFl][swSl];
    //tlsf_assert(pstCurrent && "free list cannot have a null entry");
    //tlsf_assert(pNode && "cannot insert a null entry into the free list");

    pNode->pNext_free = pstCurrent;
    pNode->pPrev_free = &control->stBlock_null;
    pstCurrent->pPrev_free = pNode;

    tlsf_assert(osMemNodeToPtr(pNode) ==
                    osMemAlignPtr(osMemNodeToPtr(pNode), ALIGN_SIZE) &&
                "pNode not aligned properly");
    /*
     * Insert the new pNode at the head of the list, and mark the first-
     * and second-level bitmaps appropriately.
     */

    control->pstBlocks[swFl][swSl] = pNode;
    control->fl_bitmap |= (1 << swFl);
    control->sl_bitmap[swFl] |= (1 << swSl);
}

/* Remove a given pNode from the free list. */
LITE_OS_SEC_TEXT static VOID osMemNodeRemove(control_t *control, LOS_MEM_DYN_NODE *pNode)
{
    INT32 swFl, swSl;
    osMemMapInsert(osMemNodeSizeGet(pNode), &swFl, &swSl);
    osMemFreeNodeRemove(control, pNode, swFl, swSl);
}

/* Insert a given pNode into the free list. */
LITE_OS_SEC_TEXT static VOID osMemNodeInsert(control_t *control, LOS_MEM_DYN_NODE *pNode)
{
    INT32 swFl, swSl;
    osMemMapInsert(osMemNodeSizeGet(pNode), &swFl, &swSl);
    osMemFreeNodeInsert(control, pNode, swFl, swSl);
}

LITE_OS_SEC_TEXT static INT32 osMemNodeSpitCheck(LOS_MEM_DYN_NODE *pNode, UINT32 uwSize)
{
    return osMemNodeSizeGet(pNode) >= sizeof(LOS_MEM_DYN_NODE) + uwSize;
}

/* Split a pNode into two, the second of which is free. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNodeSpit(LOS_MEM_DYN_NODE *pNode, UINT32 uwSize)
{
    /* Calculate the amount of space left in the remaining pNode. */
    LOS_MEM_DYN_NODE *remaining = osMemPtrOffset((VOID *)pNode, (INT32)uwSize);

    const UINT32 remain_size = osMemNodeSizeGet(pNode) - (uwSize);

    tlsf_assert(osMemNodeToPtr(remaining) == osMemAlignPtr(osMemNodeToPtr(remaining),
                                                     ALIGN_SIZE) &&
                "remaining pNode not aligned properly");

    tlsf_assert(osMemNodeSizeGet(pNode) ==
                remain_size + uwSize);
    osMemNodeSizeSet(remaining, remain_size);
    tlsf_assert(osMemNodeSizeGet(remaining) >= block_size_min &&
                "pNode split with invalid size");

    osMemNodeSizeSet(pNode, uwSize);
    osMemFreeSet(remaining);

    return remaining;
}

/* Absorb a free pNode's storage into an adjacent previous free pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNodeAbsorb(LOS_MEM_DYN_NODE *pPrev, LOS_MEM_DYN_NODE *pNode)
{
    tlsf_assert(!osMemEndCheck(pPrev) && "previous pNode can't be last");
    /* Note: Leaves flags untouched. */
    pPrev->uwSize += osMemNodeSizeGet(pNode);
    (VOID)osMemNextLink(pPrev);
    return pPrev;
}

/* Merge a just-freed pNode with an adjacent previous free pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemPreNodeMerge(control_t *control,
                                        LOS_MEM_DYN_NODE *pNode)
{
    if (osMemPreFreeCheck(pNode)) {
        LOS_MEM_DYN_NODE *pPrev = osMemNodePre(pNode);
        tlsf_assert(pPrev && "prev physical pNode can't be null");
        tlsf_assert(os_MemFreeCheck(pPrev) &&
                    "prev pNode is not free though marked as such");
        osMemNodeRemove(control, pPrev);
        pNode = osMemNodeAbsorb(pPrev, pNode);
    }

    return pNode;
}

/* Merge a just-freed pNode with an adjacent free pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNextNodeMerge(control_t *control,
                                        LOS_MEM_DYN_NODE *pNode)
{
    LOS_MEM_DYN_NODE *pNext = osMemNodeNext(pNode);
    tlsf_assert(pNext && "next physical pNode can't be null");

    if (os_MemFreeCheck(pNext)) {
        tlsf_assert(!osMemEndCheck(pNode) && "previous pNode can't be last");
        osMemNodeRemove(control, pNext);
        pNode = osMemNodeAbsorb(pNode, pNext);
    }

    return pNode;
}

/* Trim any trailing pNode space off the end of a pNode, return to pool. */
LITE_OS_SEC_TEXT static VOID osMemFreeNodeTrim(control_t *control,
                            LOS_MEM_DYN_NODE *pNode,
                            UINT32 uwSize)
{
    tlsf_assert(os_MemFreeCheck(pNode) && "pNode must be free");
    if (osMemNodeSpitCheck(pNode, uwSize))
    {
        LOS_MEM_DYN_NODE *remaining_block = osMemNodeSpit(pNode, uwSize);
        (VOID)osMemNextLink(pNode);
        osMemPreFreeMark(remaining_block);
        osMemNodeInsert(control, remaining_block);
    }
}

/* Trim any trailing pNode space off the end of a used pNode, return to pool. */
LITE_OS_SEC_TEXT_MINOR static VOID osMemUsedNodeTrim(control_t *control,
                            LOS_MEM_DYN_NODE *pNode,
                            UINT32 uwSize)
{
    tlsf_assert(!os_MemFreeCheck(pNode) && "pNode must be used");
    if (osMemNodeSpitCheck(pNode, uwSize)) {
        /* If the next pNode is free, we must coalesce. */
        LOS_MEM_DYN_NODE *remaining_block = osMemNodeSpit(pNode, uwSize);
        osMemPreUsedMark(remaining_block);
        remaining_block->pstPreNode = pNode;

        remaining_block = osMemNextNodeMerge(control, remaining_block);
        osMemNodeInsert(control, remaining_block);
    }
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemFreeNodeTrimLeading(control_t *control,
                                               LOS_MEM_DYN_NODE *pNode,
                                               UINT32 uwSize)
{
    LOS_MEM_DYN_NODE *remaining_block = pNode;
    if (osMemNodeSpitCheck(pNode, uwSize)) {
        /* We want the 2nd pNode. */
        remaining_block = osMemNodeSpit(pNode, uwSize);
        osMemPreFreeMark(remaining_block);

        (VOID)osMemNextLink(pNode);
        osMemNodeInsert(control, pNode);
    }

    return remaining_block;
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemFreeNodeLocate(control_t *control, UINT32 uwSize)
{
    INT32 swFl = 0, swSl = 0;
    LOS_MEM_DYN_NODE *pNode = NULL;

    if (uwSize) {
        osMemMapInsert(uwSize, &swFl, &swSl);
        pNode = osMemSuitableNodeSearch(control, &swFl, &swSl);
    }

    if (pNode) {
        if (osMemNodeSizeGet(pNode) >= uwSize)
            goto EXIT;
        while (pNode->pNext_free != &control->stBlock_null)
        {
            pNode = pNode->pNext_free;
            if (osMemNodeSizeGet(pNode) >= uwSize)
                goto EXIT;
        }
        osMemMapSearch(uwSize, &swFl, &swSl);
        pNode = osMemSuitableNodeSearch(control, &swFl, &swSl);
        if (pNode == NULL || osMemNodeSizeGet(pNode) < uwSize)
            return NULL;
EXIT:
        osMemFreeNodeRemove(control, pNode, swFl, swSl);
    }

    if (pNode && !pNode->uwSize)
        pNode = NULL;

    return pNode;
}

LITE_OS_SEC_TEXT static VOID *osMemUsedNodePrepare(control_t *control, LOS_MEM_DYN_NODE *pNode, UINT32 uwSize)
{
    VOID *pPtr = NULL;
    
    if (pNode)
    {
        tlsf_assert(uwSize && "size must be non-zero");
        osMemFreeNodeTrim(control, pNode, uwSize);
        osMemUsedSet(pNode);



        /* If the operation occured before task initialization(g_stLosTask.pstRunTask was not assigned)
           or in interrupt,make the value of taskid of pNode to oxffffffff*/
        if (g_stLosTask.pstRunTask != NULL && OS_INT_INACTIVE)
        {
            OS_MEM_TASKID_SET(pNode, g_stLosTask.pstRunTask->uwTaskID);
        }
        else
        {
            /* If the task mode does not initialize, the field is the 0xffffffff */
            OS_MEM_TASKID_SET(pNode, OS_NULL_INT);
            /* TODO: the commend task-MEMUSE is not include system initialization malloc */
        }



        pPtr = osMemNodeToPtr(pNode);
    }
    else
    {
        printf("-----------------------------------------------------------------------------------------------------------\n");
        osMemInfoPrint((pool_t)control);
        printf("No suitable free block, require free node size: 0x%x\n", uwSize);
        printf("-----------------------------------------------------------------------------------------------------------\n");
        return NULL;
    }
    return pPtr;
}

/* Clear structure and point all empty lists at the null pNode. */
LITE_OS_SEC_TEXT_INIT static VOID osMemControlClear(control_t *control, UINT32 uwBytes)
{
    UINT32 uwFlIndex, uwSlIndex;

    control->stBlock_null.pNext_free = &control->stBlock_null;
    control->stBlock_null.pPrev_free = &control->stBlock_null;

    control->uwPoolSize = uwBytes;

    control->fl_bitmap = 0;
    for (uwFlIndex = 0; uwFlIndex < FL_INDEX_COUNT; ++uwFlIndex) {
        control->sl_bitmap[uwFlIndex] = 0;
        for (uwSlIndex = 0; uwSlIndex < SL_INDEX_COUNT; ++uwSlIndex) {
            control->pstBlocks[uwFlIndex][uwSlIndex] = &control->stBlock_null;
        }
    }
}

/*
 * Debugging utilities.
 */
#ifdef TSLF_CONFIG_DEBUG
LITE_OS_SEC_TEXT static UINT32 osMemNodeInsideCheck(pool_t pPool, VOID *pPtr)
{
    if (((AARCHPTR)pPtr < (AARCHPTR)osMemFirstNode(pPool))  ||
        ((AARCHPTR)pPtr > (AARCHPTR)osMemEndNode(pPool)))
        return LOS_NOK;
    else
        return LOS_OK;
}

LITE_OS_SEC_TEXT INT32 osMemMagicCheck(pool_t pPool, VOID *pPtr)
{
    const LOS_MEM_DYN_NODE *pNode = NULL;

    if(pPtr == NULL || !IS_ALIGNED(pPtr, sizeof(VOID *)))
    {
        return LOS_NOK;
    }
    else
    {
        pNode = osMemPtrToNode(pPtr);
    }

    if (pNode == osMemFirstNode(pPool))
        return LOS_OK;
    else if ((AARCHPTR)pNode->pstPreNode & (ALIGN_SIZE - 1))
        return LOS_NOK;
    else if(osMemNodeInsideCheck(pPool, pNode->pstPreNode) == LOS_NOK)
        return LOS_NOK;
    else if ((AARCHPTR)pNode == (AARCHPTR)osMemNodeNext(pNode->pstPreNode))
        return LOS_OK;
    else
        return LOS_NOK;
}

LITE_OS_SEC_TEXT UINT32 osMemInfoGet(pool_t pPool, LOS_MEM_STATUS *pstStatus)
{
    LOS_MEM_DYN_NODE *pNode = osMemFirstNode(pPool);
    UINT32 uwTotalUsedSize = 0, uwTotalFreeSize = 0, uwMaxFreeNodeSize = 0;
    UINT32 uwTmpSize = 0;
    UINTPTR uvIntSave;
    control_t *control = tlsf_cast(control_t *, pPool);

    if (pstStatus == NULL)
    {
        return LOS_NOK;
    }

    if (pPool == NULL)
    {
        PRINT_ERR("wrong mem pool addr: 0x%x\n", (UINT32)pPool);
        return LOS_NOK;
    }

    if (osMemMagicCheck(pPool, (VOID *)osMemEndPtr(pPool)) == LOS_NOK)
    {
        PRINT_ERR("wrong mem pool addr: 0x%x\n", (UINT32)pPool);
        return LOS_NOK;
    }

    uvIntSave = LOS_IntLock();

    while (pNode && !osMemEndCheck(pNode)) {
        uwTmpSize = osMemNodeSizeGet(pNode);
        if (os_MemFreeCheck(pNode))
        {
            uwTotalFreeSize += uwTmpSize;
            if (uwTmpSize > uwMaxFreeNodeSize)
                uwMaxFreeNodeSize = uwTmpSize;
        }
        else
        {
            uwTotalUsedSize += uwTmpSize;
        }
        pNode = osMemNodeNext(pNode);
    }

    pstStatus->usedSize = uwTotalUsedSize + block_start_offset;
    pstStatus->freeSize = uwTotalFreeSize;
    pstStatus->totalSize = uwMaxFreeNodeSize;
    pstStatus->allocCount = control->uwTlsf_AllocCount;
    pstStatus->freeCount = control->uwTlsf_FreeCount;

    LOS_IntRestore(uvIntSave);

    return LOS_OK;

}

LITE_OS_SEC_TEXT VOID osMemInfoPrint(pool_t pPool)
{
    LOS_MEM_POOL_INFO *pstPoolInfo = (LOS_MEM_POOL_INFO *)pPool;
    LOS_MEM_STATUS stStatus = {0};
    if (LOS_NOK == osMemInfoGet(pPool, &stStatus))
        return;

    PRINT_ERR("pool addr    pool size    total size     used size    free size   alloc Count    free Count\n    0x%-8x   0x%-8x   0x%-8x    0x%-8x   0x%-16x   0x%-13x    0x%-13x\n",
                (UINT32)pPool, pstPoolInfo->uwPoolSize, stStatus.totalSize, stStatus.usedSize, stStatus.freeSize, stStatus.allocCount, stStatus.freeCount); /*lint !e515*/
    return;
}

LITE_OS_SEC_TEXT_INIT UINT32 osMemPoolSizeGet(VOID * tlsf)
{
    control_t *control = tlsf_cast(control_t *, tlsf);
    if (tlsf == NULL)
        return LOS_NOK;

    return control->uwPoolSize;
}
#endif /* TLSF_CONFIG_DEBUG */

LITE_OS_SEC_TEXT_INIT UINT32 osMemHeadSize(VOID)
{
    return sizeof(control_t);
}

LITE_OS_SEC_TEXT_INIT pool_t osMemPoolAdd(VOID *tlsf, VOID *pPool, UINT32 uwBytes)
{
    LOS_MEM_DYN_NODE *pNode;
    LOS_MEM_DYN_NODE *pNext;

    const UINT32 uwPoolBytes = osMemAlignDown(uwBytes - block_start_offset, ALIGN_SIZE) + block_header_overhead;

    if (((AARCHPTR)pPool % ALIGN_SIZE) != 0) {
        PRINT_ERR("Memory must be aligned by %u bytes.\n", (INT32)ALIGN_SIZE);
        return NULL;
    }

    if (uwPoolBytes < block_size_min || uwPoolBytes > block_size_max)
    {
        PRINT_ERR("Memory size must be between 0x%x and 0x%x bytes.\n",
               (INT32)(block_start_offset + block_size_min),
               (INT32)(block_start_offset + block_size_max));/*lint !e515*/

        return NULL;
    }

    /*
     * Create the main free pNode. Offset the start of the pNode slightly
     * so that the pstPreNode field falls outside of the pool -
     * it will never be used.
    */
    pNode = osMemPtrOffset(pPool, -(INT32)block_header_overhead); /*lint !e570*/
    osMemNodeSizeSet(pNode, uwPoolBytes);
    osMemFreeMark(pNode);
    osMemPreUsedMark(pNode);
    osMemNodeInsert(tlsf_cast(control_t *, tlsf), pNode);
    /* Split the pNode to create a zero-size sentinel pNode. */
    pNext = osMemNextLink(pNode);
    osMemNodeSizeSet(pNext, 0);
    osMemUsedMark(pNext);
    osMemPreFreeMark(pNext);

    return pPool;
}

/*
 * TLSF main interface.
 */

LITE_OS_SEC_TEXT_INIT VOID * osMemPoolCreat(VOID *pPool, UINT32 uwBytes)
{
    if (((AARCHPTR)pPool % ALIGN_SIZE) != 0)
    {
        PRINT_ERR("Memory must be aligned to %u bytes.\n", (UINT32)ALIGN_SIZE);
        return NULL;
    }

    osMemControlClear(tlsf_cast(control_t *, pPool), uwBytes);

    return tlsf_cast(VOID *, pPool);
}

/*****************************************************************************
 Function : LOS_MemInit
 Description : Initialize Dynamic Memory pool
 Input       : pPool    --- Pointer to memory pool
               uwBytes  --- Size of memory in bytes to allocate
 Output      : None
 Return      : LOS_OK - Ok, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 OS_MemInit(VOID *pPool, UINT32 uwBytes)
{
    VOID *tlsf;
    UINTPTR uvIntSave;
    if (!pPool || uwBytes <= osMemHeadSize())
    {
        return LOS_NOK;
    }
    uvIntSave = LOS_IntLock();

    if(!IS_ALIGNED(uwBytes, ALIGN_SIZE))
    {
        PRINT_ERR("pool [0x%x, 0x%x) size 0x%x sholud be aligned with ALIGN_SIZE\n",
                  (UINT32)pPool, (AARCHPTR)pPool + uwBytes, uwBytes);/*lint !e515*/
        uwBytes = osMemAlignDown(uwBytes, ALIGN_SIZE);
    }


    tlsf = osMemPoolCreat(pPool, uwBytes);
    if (osMemPoolAdd(tlsf, (UINT8 *)pPool + osMemHeadSize(), uwBytes - osMemHeadSize()) == 0)
    {
        LOS_IntRestore(uvIntSave);
        return LOS_NOK;
    }

    LOS_IntRestore(uvIntSave);
    return LOS_OK;
}



LITE_OS_SEC_TEXT VOID *os_HeapAlloc(VOID *tlsf, UINT32 uwSize)
{
    UINT32 adjust;
    LOS_MEM_DYN_NODE *pNode;
    VOID *pPtr = NULL;
    control_t *control = tlsf_cast(control_t *, tlsf);

    adjust = osMemReqSizeAdjust(uwSize, ALIGN_SIZE);
    if(0 == adjust)
    {
        PRINT_ERR("require node size 0x%x is too large\n",uwSize);
        return NULL;
    }
    printf("control,adjust is %p,%p\r\n",(UINT32)tlsf,(UINT32)adjust);
    pNode = osMemFreeNodeLocate(control, adjust);
    pPtr = osMemUsedNodePrepare(control, pNode, adjust);

    if (NULL != pPtr)
    {
        control->uwTlsf_AllocCount++;
    }

    return pPtr;
}

/*****************************************************************************
 Function : LOS_MemAlloc
 Description : Allocate Memory from Memory pool
 Input       : tlsf    --- Pointer to memory pool
               uwSize  --- Size of memory in bytes to allocate
 Output      : None
 Return      : Pointer to allocated memory
*****************************************************************************/
LITE_OS_SEC_TEXT VOID *OS_MemAlloc(VOID * tlsf, UINT32 uwSize)
{
    VOID *pPtr = NULL;
    UINTPTR uvIntSave;

    if ((0 == uwSize) || (NULL == tlsf) || (uwSize > block_size_max))
    {
        return NULL;
    }
    uvIntSave = LOS_IntLock();

    {
        pPtr = os_HeapAlloc(tlsf, uwSize);
    }
    LOS_IntRestore(uvIntSave);
    return pPtr;
}


LITE_OS_SEC_TEXT BOOL os_HeapFree(VOID * tlsf, VOID *pPtr)
{
    control_t *control;

    LOS_MEM_DYN_NODE *pNode;

    control = (LOS_MEM_POOL_INFO *)tlsf;
    pNode = osMemPtrToNode(pPtr);

    if (os_MemFreeCheck(pNode))
    {
        return FALSE;
    }

    if (osMemMagicCheck(tlsf, pPtr) == LOS_NOK)
    {
        return FALSE;
    }

    osMemFreeSet(pNode);
    pNode = osMemPreNodeMerge(control, pNode);
    pNode = osMemNextNodeMerge(control, pNode);
    osMemNodeInsert(control, pNode);

    control->uwTlsf_FreeCount++;

    return TRUE;
}

/*****************************************************************************
 Function : LOS_MemFree
 Description : Free Memory and return it to Memory pool
 Input       : tlsf     --- Pointer to memory pool
               pPtr     --- Pointer to memory to free
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 OS_MemFree(VOID * tlsf, VOID *pPtr)
{
    UINTPTR uvIntSave;
    BOOL uwRet;


    if ((NULL == tlsf) || (NULL == pPtr))
    {
        return LOS_NOK;
    }
    uvIntSave = LOS_IntLock();
 
            uwRet = os_HeapFree(tlsf,pPtr);

    LOS_IntRestore(uvIntSave);
    return (uwRet == TRUE ? LOS_OK : LOS_NOK);
}



LITE_OS_SEC_TEXT UINT32 OS_MemStatisticsGet(VOID *pPool, LOS_MEM_STATUS *pstStatus)
{
    LOS_MEM_POOL_INFO *pstPoolInfo = (LOS_MEM_POOL_INFO *)pPool;
    LOS_MEM_STATUS stStatus;
    if (LOS_NOK == osMemInfoGet(pPool, &stStatus))
    {
        return LOS_NOK;
    }

    pstStatus->totalSize  = stStatus.totalSize;
    pstStatus->usedSize   = stStatus.usedSize;
    pstStatus->freeSize   = stStatus.freeSize;
    pstStatus->allocCount = stStatus.allocCount;
    pstStatus->freeCount  = stStatus.freeCount;

    return LOS_OK;
}

/**
 * sclist main function
 */
LITE_OS_SEC_TEXT UINT32 TIDEqual(TIdentifier TI1, TIdentifier TI2)
{
    if(TI1.TID != TI2.TID)
    {
        return LOS_NOK;
    }
    UINT16 i = 0;
    while(TI1.Identifier[i] != '\0' && TI2.Identifier[i] != '\0')
    {
        if(TI1.Identifier[i] != TI2.Identifier[i])
        {
            return LOS_NOK;
        }
        i++;
    }
    if(TI1.Identifier[i] != '\0' || TI2.Identifier[i] != '\0')
    {
        return LOS_NOK;
    }
    return LOS_OK;
    
}

/*****************************************************************************
 Function : osFoundVIB
 Description : Found the target VIB
 Input       : TID, Identifier 
 Output      : None
 Return      : VIB  --- Pointer to the VIB
*****************************************************************************/
LITE_OS_SEC_TEXT VOID *osFoundVIB(UINT8 TID, UINT8 Identifier[])
{
    TVCB *curTVCB = (TVCB *)g_TVBHead;
    VIB *curVIB = NULL;
    TIdentifier curVar;
    UINT8 TVCBCount = 0;
    curVar.TID = TID;
    memcpy(curVar.Identifier, Identifier, 9);//curVar.Identifier = Identifier;
    while((curTVCB->varNum == 0) ||  (curTVCB->TID != TID))
    {
        curTVCB = (TVCB *)((UINT32)curTVCB + g_TVCBSize);
        if(TVCBOverflow(curTVCB) == LOS_NOK)
        {
            return NULL;
        }
    }
    if(curTVCB->TID == TID)
    {
 //       printf("the found TVCB  is %p\r\n",(curTVCB));
        curVIB = OS_SCLIST_VIB_ADDR(curTVCB);                        /*skip the length of the parameter varNum*/
        while(((TIDEqual(curVIB->varName, curVar)) == LOS_NOK) && (curVIB < curTVCB + g_TVCBSize))
        {
            curVIB ++;
        }
        if(TIDEqual(curVIB->varName, curVar) == LOS_OK)
        {
            printf("the found vib  is %p\r\n\n",(curVIB));
            printf("the found vib addrstart is %p\r\n\n",OS_ADDR16to32(curVIB->addrStart));
            return (VOID *)curVIB;
        }
    }
    return NULL;
}

/*****************************************************************************
 Function : osCreateVIB
 Description : Create the target VIB
 Input       : *pRet, Identifier, BlkNum, 
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 osCreateVIB(VOID *pRet, UINT8 curTID, UINT8 Identifier[], UINT16 BlkNum)
{
    TVCB *curTVCB = (TVCB *)g_TVBHead;
//    printf("the begin tvcb is %p\r\n",curTVCB);
    VIB *curVIB = NULL;
    TIdentifier curVar;
    UINT8 TVCBCount = 0;
    VIB *curVIBBackup = NULL;
    curVar.TID = curTID;
    memcpy(curVar.Identifier, Identifier, 9);
    curVar.Identifier[8] = '\0';
    while(((curTVCB->TID != curTID) && (curTVCB->varNum != 0)) && (TVCBCount <= g_TVCBNum))
    {
 //       printf("curtvcb.tid,num =%d,%d\r\n",curTVCB->TID,curTVCB->varNum);
        curTVCB = (TVCB *)((UINT32)curTVCB + g_TVCBSize);
        TVCBCount++;
    }
 //   printf("the create tvcb is %p,tvcbcount = %d\r\n",curTVCB,TVCBCount);
    if(TVCBCount > g_TVCBNum)
    {
        return LOS_NOK;
    }
    curVIB = OS_SCLIST_VIB_ADDR(curTVCB); 
    if(curTVCB->varNum == 0)
    {
 //       printf("the varnum is %d\r\n",curTVCB->varNum);
        curTVCB->TID = curTID;
    }
    else
    {
 //       printf("the varnum is %d\r\n",curTVCB->varNum);
        if(curTVCB->varNum * g_VIBSize > g_TVCBSize)
        {
            
            return LOS_NOK;
        }
        UINT8 varCount = 1;
        while((TIDEqual(curVIB->varName, curVar) == LOS_NOK) && (isnotEmpty(curVIB->addrStart)))
        {
            curVIB ++;
            varCount++;
        }
    }
    curVIB->addrStart.HI16 = (UINT16)(((UINT32)pRet & 0xFFFF0000)>>16);
    curVIB->addrStart.LO16 = (UINT16)((UINT32)pRet & 0x0000FFFF);
    // printf("the create vib addrstart is %p\r\n",OS_ADDR16to32(curVIB->addrStart));
    // printf("the create vib  is %p\r\n",(UINT32)curVIB);
    curVIB->varBlkNum = BlkNum;
    curVIB->varName = curVar;
    // printf("the create vib name is %s\r\n",curVIB->varName.Identifier);
    curVIB->varCRC = calc_crc16(0, curVIB, 16);
    curTVCB->varNum++;
    curVIBBackup = (VIB *)((UINT32)curVIB + (UINT32)g_TVCBSize * (UINT32)g_TVCBNum);
    memcpy(curVIBBackup, curVIB, sizeof(VIB));
    return LOS_OK;
}

/*****************************************************************************
 Function : osDeleteVIB
 Description : Delete the target VIB
 Input       : *pRet
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 osDeleteVIB(VOID *pRet)
{
    UINT32 uwRet = LOS_NOK;
    VIB *curVIB = (VIB *) pRet;
    VIB *BackupVIB;
    curVIB->addrStart.HI16 = 0;
    curVIB->addrStart.LO16 = 0;
    curVIB->varBlkNum = 0;
    curVIB->varCRC = 0;
    BackupVIB = (VIB *)((UINT32)curVIB + (UINT32)g_TVCBSize * (UINT32)g_TVCBNum);
    memcpy(BackupVIB, curVIB, sizeof(VIB));
   ((TVCB *)(curVIB->fromTVCB))->varNum --;
    return LOS_OK;
}

/*****************************************************************************
 Function : osCheckCRC
 Description : Check whether the CRC is valid
 Input       : VIB  --- Pointer to the VIB
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 osCheckCRC(VOID *VIBInfo)
{
    UINT16 curCRC;
    curCRC = calc_crc16(0,VIBInfo, 16);
    if (((VIB *)VIBInfo)->varCRC == curCRC)
    {
        return LOS_OK;
    }
    else
    {
        return LOS_NOK;
    }
}

/*****************************************************************************
 Function : osRecoverSClist
 Description : recover sclist from sclist2
 Input       : sclist2  --- Pointer to the sclist2
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT VOID osRecoverSClist(VIB *curVIB)
{
    VIB *BackupVIB;
    BackupVIB = (VIB *)((UINT32)curVIB + (UINT32)g_TVCBSize * (UINT32)g_TVCBNum);
    memcpy(curVIB, BackupVIB, sizeof(VIB));
}

/*****************************************************************************
 Function : osIndexInit
 Description : Init index area
 Input       : None
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 osIndexInit(VOID *TVCB_Head)
{
    TVCB *curTVCB = (TVCB *)TVCB_Head;
    VIB *curVIB = NULL;
    UINT32 TVBLength = g_TVCBNum * g_TVCBSize;
    while(curTVCB < (UINT32)TVCB_Head + TVBLength)
    {
        curTVCB->TID = 0;
        curTVCB->varNum = 0;
        
        curVIB = OS_SCLIST_VIB_ADDR(curTVCB);  
        do
        {
            curVIB->addrStart.HI16 = 0;
            curVIB->addrStart.LO16 = 0;
            curVIB->varBlkNum = 0;
            curVIB->varCRC = 0;
            curVIB->fromTVCB = (VOID *)curTVCB;
            curVIB ++;
        } while (curVIB < curTVCB);
        curTVCB = (TVCB *)((UINT32)curTVCB + g_TVCBSize);
    }
    return LOS_OK;
}

/*****************************************************************************
 Function : LOS_pcramboxInit
 Description : Initialize Static Memory pool
 Input       : pBoxMem    --- Pointer to the memory pool
               uwBoxSize  --- Size of the memory pool
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_pcramboxInit(VOID *pBoxMem, UINT32 uwBoxSize)
{
    VOID *pstNode = NULL;
    UINT16 i;
    UINTPTR uvIntSave;
    UINT32 uwRet = LOS_NOK;

    g_TVBHead = (VOID *)((UINT32)pBoxMem + pcrambox_magicsize);

    g_TVCBNum = 20;
    g_VIBSize = sizeof(VIB);

    g_TVCBSize = sizeof(TVCB) + g_VIBSize * 20;
    if(*((UINT16 *)pBoxMem) == 0xFFAA)
    {
        return LOS_OK;
    }
    uwBoxSize -= (2 * g_TVCBSize * g_TVCBNum + pcrambox_magicsize);
    if (pBoxMem == NULL ||  uwBoxSize < sizeof(LOS_MEM_POOL_INFO))
    {
        return LOS_NOK;
    }

    //uvIntSave = LOS_IntLock();
    /*
     * The node size is aligned to the next 4 boundary.
     * Memory that is not enough for one node size in the memory pool will be ignored.
     */
    uwRet = osIndexInit(g_TVBHead);
    if(uwRet != LOS_OK)
    {
       // LOS_IntRestore(uvIntSave);
       
        return LOS_NOK;
    }
    else
    {
        uwRet = osIndexInit((VOID *)((UINT32)g_TVBHead + g_TVCBNum * g_TVCBSize));        /* SCLIST2 INIT */
    }
    
    /*
     * calc the length of the index area
     * SKIP the index area(SClist1 & SCLIST2)
     * The PCRAM pool is divided into two parts, INDEX area as well as FREE MEMORY NODE area
     */
    pstNode = (VOID *)((UINT32)pBoxMem + (UINT32)(2 * g_TVCBNum * g_TVCBSize) + pcrambox_magicsize);
    uwRet = OS_MemInit((VOID *)(BOXMEM_ALIGN(pstNode,OS_BOXMEM_BASE_ALIGN)), BOXMEM_ALIGN(uwBoxSize - OS_BOXMEM_BASE_ALIGN, OS_BOXMEM_BASE_ALIGN));
    if(uwRet != LOS_OK)
    {
        return LOS_NOK;
    }
    OS_pcrambox_SET_MAGIC(pBoxMem);
    return LOS_OK;
}

/*****************************************************************************
 Function : SC_MALLOC
 Description : Allocate sc block from pcram Memory pool
 Input       : pBoxMem  --- Pointer to memory pool
 Output      : None
 Return      : Pointer to allocated memory block
*****************************************************************************/
LITE_OS_SEC_TEXT VOID *SC_MALLOC(UINT8 Identifier[], UINT32 Length, UINT8 *Flag)
{
    UINT8 TID;
    UINT32 uwRet = LOS_NOK;
    UINTPTR uvIntSave;
    VOID *pRet;
    //uvIntSave = LOS_IntLock();
    TID = (UINT8)LOS_CurTaskIDGet();
    if(TID == LOS_ERRNO_TSK_ID_INVALID)
    {
        //LOS_IntRestore(uvIntSave);
        return NULL;
    }
    printf("TID:%d    Name:%s    want MALLOC\r\n", TID, Identifier);
    pRet = osFoundVIB(TID, Identifier);
    
    if(pRet != NULL)
    {
        uwRet = osCheckCRC(pRet);
        if(uwRet != LOS_OK)
        {
            osRecoverSClist((VIB *)pRet);
        }
        if(*Flag == 0)
        {
            LOS_pcramboxClr(OS_PCRAM_START_ADDR , (VOID *)(OS_ADDR16to32(((VIB *)pRet)->addrStart)), Length);
            *Flag = 1;
            //LOS_IntRestore(uvIntSave);
            return (VOID *)(OS_ADDR16to32(((VIB *)pRet)->addrStart));
        }
        else
        {
            return (VOID *)(OS_ADDR16to32(((VIB *)pRet)->addrStart));
        }
        
    }
    else
    {
        pRet = OS_MemAlloc(BOXMEM_ALIGN(pcram_mempool_addr(OS_PCRAM_START_ADDR),OS_BOXMEM_BASE_ALIGN), Length);
        if(pRet != NULL)
        {
            printf("%s alloc success!!\r\n", Identifier);
            uwRet = osCreateVIB(pRet, TID, Identifier, Length);
            LOS_pcramboxClr(OS_PCRAM_START_ADDR , pRet, Length);
            *Flag = 0;
            //LOS_IntRestore(uvIntSave);
            
            return pRet;
        } 
        else
        {
            printf("alloc failed!!\r\n");
            //LOS_IntRestore(uvIntSave);
            return NULL;
        }
        
    }
}



/*****************************************************************************
 Function : SC_FREE
 Description : Allocate sc block from pcram Memory pool
 Input       : pBoxMem  --- Pointer to memory pool
 Output      : None
 Return      : Pointer to allocated memory block
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 SC_FREE(UINT8 Identifier[])
{
    UINT8 TID;
    UINT32 uwRet = LOS_NOK;
    UINT16 BlkNum, uwBlkSize;
    UINTPTR uvIntSave;
    VOID *pRet;
    uvIntSave = LOS_IntLock();
    TID = LOS_CurTaskIDGet();
    if(TID == LOS_ERRNO_TSK_ID_INVALID)
    {
        (VOID)LOS_IntRestore(uvIntSave);
        return LOS_NOK;
    }
    pRet = osFoundVIB(TID, Identifier);
    if(pRet == NULL)
    {
        (VOID)LOS_IntRestore(uvIntSave);
        return LOS_NOK;
    }
    uwRet =OS_MemFree(BOXMEM_ALIGN(pcram_mempool_addr(OS_PCRAM_START_ADDR),OS_BOXMEM_BASE_ALIGN), (VOID *)(OS_ADDR16to32(((VIB *)pRet)->addrStart)));
    if(uwRet == LOS_OK)
    {
        uwRet = osDeleteVIB(pRet);
    }
    else
    {
        (VOID)LOS_IntRestore(uvIntSave);
        return LOS_NOK;
    }
    (VOID)LOS_IntRestore(uvIntSave);
    return uwRet;
}

/*****************************************************************************
 Function : LOS_pcramboxClr
 Description : Clear the memory block
 Input       : pBoxMem  --- Pointer to memory pool
               pBox     --- Pointer to memory block to clear
               BlkNum   --- the number of the block need to clear
 Output      : None
 Return      : None
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR VOID LOS_pcramboxClr(VOID *pBoxMem, VOID *pBox, UINT32 Length)
{
    if (pBoxMem == NULL || pBox == NULL)
    {
        return;
    }

    memset(pBox, 0, Length);
}

/*****************************************************************************
 Function : LOS_pcramboxStatisticsGet
 Description : Get information about pcrambox
 Input       : pBoxMem     --- Pointer to the calculate pcrambox
 Output      : puwMaxBlk   --- Record the total number of pcrambox
               puwBlkCnt   --- Record the number of the allocated blocks of pcrambox
               puwBlkSize  --- Record the block size of pcrambox
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_pcramboxStatisticsGet(VOID *pBoxMem, LOS_MEM_STATUS *pstStatus)
{
    OS_MemStatisticsGet(BOXMEM_ALIGN(pcram_mempool_addr(OS_PCRAM_START_ADDR),OS_BOXMEM_BASE_ALIGN), pstStatus);
    return LOS_OK;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
